package com.iqik.base.sync;

// synchronized 关键字可以放置方法返回值前任意位置，要注意到sleep()不会释放对监视器的锁定

/**
 * synchronized特点：
 *  1。可重入性
 *  2。当代码执行结束或者出现异常后自动释放对监视器的锁定
 *  3。是非公平锁，在等待获取锁的过程中不可被中断
 *  4。synchronized的内存语义
 *  5。互斥性，被synchronized修饰的方法同事只能由一个线程执行。
 */
public class Synchronized {

    private void sleep() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void instanceMethod() {
        for (int i = 0; i < 5; i++) {
            System.out.println("instanceMethod");
            sleep();
        }
    }

    public synchronized static void staticMethod() {
        for (int i = 0; i < 5; i++) {
            System.out.println("staticMethod");
            new Synchronized().sleep();
        }
    }

    public void thisMethod() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                System.out.println("thisMethod");
                sleep();
            }
        }
    }

    public void anyObject() {
        synchronized ("anything") {
            for (int i = 0; i < 5; i++) {
                System.out.println("anyObject");
                sleep();
            }
        }
    }

    public static void main(String[] args) {
        /**
         * 输出总以5个最小单位交替出现，证明synchronized(this) 和实例方法上使用synchronized使用的是同一监视器。
         * 如果去掉任意方法上的synchronized或者全部去掉，则会出现instanceMethod和thisMethod无规律的交替输出。
         */
        Synchronized synchronized_ = new Synchronized();
        for (int i = 0; i < 10; i++) {
            new Thread() {
                @Override
                public void run() {
                    synchronized_.thisMethod();
                }
            }.start();
            new Thread() {
                @Override
                public void run() {
                    synchronized_.instanceMethod();
                }
            }.start();
        }
    }

}
